home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Practical Algorithms for Image Analysis
/
Practical Algorithms for Image Analysis.iso
/
TARFILE.GZ
/
tarfile
/
ch_4.3
/
xah
/
xah.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-11
|
12KB
|
522 lines
/*
* xah.c
*
* Practical Algorithms for Image Analysis
*
* Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
*/
/*
* X(Extract) A(rea) H(istogram)
*
*/
#include "xah.h"
#define ON 1
#define OFF 0
#define DISABLE -1
#define PROMPT_CUTOFF OFF /* prompt for cutoff value(ON/OFF) */
#define DISPL_AOI OFF
#define SCL_AOI OFF
#define BIN_AOI ON /* binarize separate AOI (ON) or */
/* binarize and scan same AOI (OFF) */
/* disable binarization */
#define LIM_AREA ON /* limit range of dom areas */
#define WRITE_FILE ON /* prompt for outp file name */
#define WRITE_ALL ON /* dump bub data to addit outp file */
#define IP_TOOL ON
#define MAX_ND 10000 /* max permiss. number of domains */
#define NSQ 6 /* histogram limited to NSQ*sigma */
#define DEFAULT 0 /* scale hist by min and max data */
#define FIX_BINWD 1
#define FIX_RANGE 2 /* restr. range, center at mean */
#define FIX_INTERVAL 3 /* preset min AND max data */
#define MIN_ND 5 /* min no domains for area histog */
#define BUF_SZ 256 /* sz of input file buffer */
#define SHOW_HIST
#define DBG_HIST
#define DEBUG
#define S_DEBUG
/*
* Global Variables
*/
static char HffPath[129]; /* path for HFF files */
static char Scratch[32]; /* Scratch pad temporary buffer */
static char *fn_prompt =
{"...filename (.hdt)?"};
static char hbuf[BUF_SZ], *phbuf = &hbuf[0]; /* file name buf for hdt output file */
static char vbuf[BUF_SZ], *pvbuf = &vbuf[0]; /* file name buf for vin output file */
static char gbuf[BUF_SZ], *pgbuf = &gbuf[0]; /* file name buf for gdt output file */
extern char *optarg;
extern int optind, opterr;
extern short tiffInput; /* flag=0 if no ImageIn to set tags; else =1 */
int SORT_STAT = 1; /* flag to ind sorted inp to eval_hist() */
int CDYN = 1; /* flags ind data type */
int X_SQ = 1; /* when set, eval hist of SQRT(area/mean_a) */
/*
* error message
*/
void
exitmess (prompt, status)
char *prompt;
int status;
{
printf (prompt);
printf ("\n");
exit (status);
}
void
fail_alloc (char *str, int code)
{
printf ("\n...memory alloc for %s failed\n", str);
exit (code);
}
/*
* comparison of two elements in area array (for qsort)
* here: array elements are of type unsigned int
*/
int
compare (a1, a2)
int *a1;
int *a2;
{
return ((int) SIGN (*a1 - *a2));
}
/* sort bubble structure on y, then x, coord */
int
bcomp (b1, b2)
struct bubble *b1;
struct bubble *b2;
{
if (b1->ctr.y < b2->ctr.y)
return (-1);
if (b1->ctr.y > b2->ctr.y)
return (1);
if (b1->ctr.x < b2->ctr.x)
return (-1);
if (b1->ctr.x > b2->ctr.x)
return (1);
return (0);
}
/*
* usage of routine
*/
void
usage (char *progname)
{
progname = last_bs (progname);
printf ("USAGE: %s inimg outimg [-a x1 y1 x2 y2] [-L]\n", progname);
printf ("\n%s constructs area moments and area histogram,\n", progname);
printf ("of image containing domains (\"blobs\");\n");
printf ("the output image is a point pattern representing\n");
printf ("the domain centroids; also evaluates histogram of\n");
printf ("domain areas\n\n");
printf ("ARGUMENTS:\n");
printf (" inimg: input image filename (TIF)\n");
printf (" outimg: output image filename (TIF)\n\n");
printf ("OPTIONS:\n");
printf (" -a x1 y1 x2 y2: upper left(x1, y1), lower right(x2, y2)\n");
printf (" coords of area to scan (int);\n");
printf (" default is area of imgin\n");
printf (" -L: print Software License for this module\n");
exit (1);
}
void
main (int argc, char **argv)
{
struct bubble *ocbub, *rcbub, *cbub;
unsigned int *oarea, *rarea, *area;
double mean_a, sdev_a, skew_a;
double del_a;
int id, nd, ird;
int c;
float *farea;
int BIN_METHOD = DEFAULT; /* select binning criterion */
/* float *ahst; */
struct Histo *ah;
double foo = 1.0;
int nparms = 3;
FILE *wfp, *vfp, *gfp;
Image *imgIn;
Image *imgOut;
int aoi_height;
int aoi_width;
int i_arg;
int x1 = -1, y1 = -1, x2 = -1, y2 = -1;
char in_buf[IN_BUF_LEN];
/*
* cmd line options
*/
static char *optstring = "a:L";
/*
* parse command line
*/
optind = 3; /* set getopt to point to the start of the arg list */
opterr = ON; /* give error messages */
if (argc < 3)
usage (argv[0]);
while ((i_arg = getopt (argc, argv, optstring)) != EOF) {
switch (i_arg) {
case 'a':
if (!sscanf (argv[optind - 1], "%d", &x1) || !sscanf (argv[optind], "%d", &y1)
|| !sscanf (argv[optind + 1], "%d", &x2) || !sscanf (argv[optind + 2], "%d", &y2)) {
printf ("Error getting values for area to scan\n");
printf ("Will attempt to scan entire picture\n");
}
break;
case 'L':
print_sos_lic ();
exit (0);
default:
printf ("\ngetopt: unknown condition encountered\n");
exit (1);
break;
}
}
/*
* Read input image
*/
imgIn = ImageIn (argv[1]);
if (imgIn->bps == 8 && imgIn->spp == 3) {
printf ("Got RGB image!!!\nInput image must be Grayscale or B&W!!\n");
exit (1);
}
if (x1 == -1 || y1 == -1 || x2 == -1 || y2 == -1) {
x1 = 0;
y1 = 0;
x2 = imgIn->width - 1;
y2 = imgIn->height - 1;
}
else if (x1 < 0 || x1 >= imgIn->width
|| y1 < 0 || y1 >= imgIn->height
|| x2 < 0 || x2 >= imgIn->width
|| y2 < 0 || y2 >= imgIn->height
|| x1 > x2 || y1 > y2) {
printf ("Invalid values for area to scan\n");
printf ("Setting to size of input image\n");
x1 = 0;
y1 = 0;
x2 = imgIn->width - 1;
y2 = imgIn->height - 1;
}
aoi_height = y2 - y1 + 1;
aoi_width = x2 - x1 + 1;
/*
* Allocate memory for output image
*/
imgOut = ImageAlloc (aoi_height, aoi_width, imgIn->bps);
/*
* Draw a 255 border around image to eliminate
* edge effects for line fills
*/
draw_rect (0, 0, imgOut->width - 1, imgOut->height - 1, imgIn, WHITE);
/*
* measure and record domain areas, mark and record domain centroids
*/
if ((ocbub = (struct bubble *) calloc (MAX_ND, sizeof (struct bubble))) == NULL)
fail_alloc ("ocbub", 1);
nd = ah_AOI (x1, y1, x2, y2, imgIn, imgOut, ocbub, MAX_ND);
ImageOut (argv[2], imgOut);
if ((oarea = (unsigned int *) calloc (MAX_ND, sizeof (unsigned int))) == NULL)
fail_alloc ("oarea", 1);
/*
* sort area array
*/
if (nd > MIN_ND) {
extract_area (nd, oarea, &ocbub[0]);
#ifdef DEBUG
for (id = 0; id < nd; id++) {
printf (" %6u", (ocbub + id)->area);
if ((id + 1) % 8 == 0)
printf ("\n");
}
#endif
}
else {
printf ("\n...number of domains below lower limit of %d\n",
MIN_ND);
exit (1);
}
/*
* evaluate moments
*/
#ifdef DBG_HIST
printf ("\n...evaluating mean area (area array):");
#endif
mean_a = eval_mean (nd, oarea);
printf (" (raw) mean area: %6.2lf", mean_a);
#ifdef DBG_HIST
printf ("\n...evaluating rmsq (area array):");
#endif
sdev_a = eval_sdev (mean_a, nd, oarea);
printf ("...rmsq dev: %6.2lf", sdev_a);
#ifdef DBG_HIST
printf ("\n...evaluating skew (area array):");
#endif
skew_a = 0.0;
if (sdev_a > 0.01) {
skew_a = eval_skew (mean_a, sdev_a, nd, oarea);
printf ("...skew: %6.2lf", skew_a);
}
printf ("\n");
/*
* in imgOut, generate a display of the pattern marking sites
* by UPW_TRIANGLE if the corresponding area exceeds mean_a, and
* by a DNW_TRIANGLE otherwise
*/
encode_ba (mean_a, sdev_a, ocbub, nd, imgOut, GRAY);
/*
* limit values in array oarea to those within a spread of NSQ*sdev_a
* to eliminate artefacts
*/
area = oarea;
cbub = ocbub;
if (LIM_AREA == ON) {
if ((rarea = (unsigned int *) calloc (nd, sizeof (unsigned int))) == NULL)
fail_alloc ("rarea", 1);
if ((rcbub = (struct bubble *) calloc (nd, sizeof (struct bubble))) == NULL)
fail_alloc ("rcbub", 1);
ird = 0;
for (id = 0; id < nd; id++) {
del_a = (double) (*(oarea + id)) - mean_a;
if (fabs (del_a) <= NSQ * sdev_a) {
*(rarea + ird) = *(oarea + id);
*(rcbub + ird) = *(ocbub + id);
ird++;
}
}
nd = ird;
printf ("...%d domains within %d*std dev of mean area:\n",
nd, NSQ);
/*
* handle memory alloc
*/
rarea = (unsigned int *) realloc (rarea, nd * sizeof (unsigned int));
rcbub = (struct bubble *) realloc (rcbub, nd * sizeof (struct bubble));
area = rarea;
cbub = rcbub;
#ifdef DEBUG
printf ("...domain areas within %d*rmsq of mean...\n", NSQ);
for (id = 0; id < nd; id++) {
printf (" %6u", (cbub + id)->area);
if ((id + 1) % 8 == 0)
printf ("\n");
}
printf ("\n");
#endif
}
/*
* bin data into histogram
*/
#ifdef DBG_HIST
printf ("\n...evaluate area histogram...\n");
#endif
printf ("...sorting %d domains by area...\n", nd);
#if defined(LINUX)
qsort (area, (size_t) nd, sizeof (unsigned int), (__compar_fn_t) compare);
#else
qsort (area, (size_t) nd, sizeof (unsigned int), compare);
#endif
#ifdef S_DEBUG
printf ("...domain area array after sorting...\n");
for (id = 0; id < nd; id++) {
printf (" %6u", *(area + id));
if ((id + 1) % 8 == 0)
printf ("\n");
}
#endif
/*
* for generality's sake, convert to float
*/
if ((farea = (float *) calloc (nd, sizeof (float))) == NULL)
fail_alloc ("farea", 1);
for (id = 0; id < nd; id++)
*(farea + id) = (float) (*(area + id));
/*
* for domain coarsening data
*/
if (CDYN == 1) {
for (id = 0; id < nd; id++) {
*(farea + id) /= (float) (mean_a);
if (X_SQ == ON) {
*(farea + id) = (float) sqrt (*(farea + id));
}
}
BIN_METHOD = FIX_INTERVAL;
}
ah = eval_hist (BIN_METHOD, farea, nd, 1);
ah->mean = mean_a;
ah->sdev = sdev_a;
ah->skew = skew_a;
printf ("\n\n...histogram of %d domain areas (norm by raw mean):\n", nd);
printf (" max(pix): %6.2f", ah->amax);
printf (" min(pix): %6.2f", ah->amin);
printf (" bin_w(pix): %6.3f\n", ah->bw);
printf (" hist mean(pix): %6.2lf\n", ah->hmean);
/*
* write histogram data to file
*/
if (WRITE_FILE == ON) {
c = 0;
printf ("\n...write files (.hdt, .vin and .gdt)?(y/n)");
while ((c != 'y') && (c != 'n'))
c = readlin (in_buf);
if (c == 'y') {
printf ("...enter fn [drive:][\\directory\\]: ");
readlin (in_buf);
strcpy (hbuf, in_buf);
strcpy (vbuf, in_buf);
strcpy (gbuf, in_buf);
strcat (hbuf, ".hdt");
strcat (vbuf, ".vin");
strcat (gbuf, ".gdt");
if ((wfp = fopen (hbuf, "w")) == NULL) {
fprintf (stderr, "could not open output file %s\n", hbuf);
exit (1);
}
printf ("writing data file: %s\n", hbuf);
write_aoi_data (wfp, (float) foo, nparms, ah, X_SQ);
if ((gfp = fopen (gbuf, "w")) == NULL) {
fprintf (stderr, "could not open output file %s\n", gbuf);
exit (1);
}
#if defined(LINUX)
qsort (cbub, nd, sizeof (struct bubble), (__compar_fn_t) bcomp);
#else
qsort (cbub, nd, sizeof (struct bubble), bcomp);
#endif
printf ("writing data file: %s\n", gbuf);
write_bub_data (gfp, (float) foo, nparms, &cbub[0], nd);
if ((vfp = fopen (vbuf, "w")) == NULL) {
fprintf (stderr, "could not open output file %s\n", vbuf);
exit (1);
}
printf ("writing data file: %s\n", vbuf);
write_vin_file (vfp, nd, x1, y1, x2, y2, cbub);
fclose (wfp);
fclose (vfp);
fclose (gfp);
}
}
/*
* release resources
*/
if (LIM_AREA == ON) {
free (rarea);
free (rcbub);
}
free (ocbub);
free (oarea);
free (farea);
free (ah->ph);
free (ah); /* alloc in aoi_hist */
}
/*
* extract area values into separate array
*/
void
extract_area (int nd, unsigned int *area, struct bubble *cbub)
{
int id;
for (id = 0; id < nd; id++)
*(area + id) = (cbub + id)->area;
}